package com.kuang.bascic.Interceptor;

import com.kuang.bascic.annotation.PreAuthorize;
import com.kuang.jwt.*;
import com.kuang.system.mapper.PermissionMapper;
import com.kuang.system.mapper.RoleMapper;
import com.kuang.system.service.PermissionService;
import com.kuang.user.domian.LoginInfo;
import jdk.internal.org.objectweb.asm.Handle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private PermissionMapper permissionMapper;
    @Value("${jwt.rsa.pub}")// SPEL表达式读取配置文件中的值
    private String jwtRsaPrivate;
    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object Obj) throws Exception {
        // 配置前端拦截器
        // 从前端请求头里获取到token 对比redis里的  判断是否存在  判断是否合法过期
        // 登录拦截器
        String token = req.getHeader("U-TOKEN");
        String token1 = req.getHeader("token");// 现在获取的是存储的后台服务器的jwt权限
        if (token1!=null){
            //表明请求里有token 现在去判断是是否合法在redis里
//            Object o = redisTemplate.opsForValue().get(token);
            // 解密token拿到用户权限和菜单
            PublicKey publicKey = RsaUtils
                    .getPublicKey(FileCopyUtils
                            .copyToByteArray(this.getClass().getClassLoader().getResourceAsStream(jwtRsaPrivate)));
            // 解密的token
            Payload<UserInfo> payload = JwtUtils.getInfoFromToken(token1, publicKey, UserInfo.class);
            //获取解密的用户信息
            UserInfo userInfo = payload.getUserInfo();
            LoginInfo lf = userInfo.getLoginInfo();
            if (lf!=null){
                // url拦截判断
                 // 判断当前用户是否是主站用户， 如果是直接放行，不是继续执行
//                LoginInfo lf= (LoginInfo) o;
                if (lf.getType()==0){
                    // 那到当前访问的方法（反射）
                    HandlerMethod handlerMethod= (HandlerMethod) Obj;
                    Method method = handlerMethod.getMethod();
                    // 拿到注解
                    PreAuthorize annotation = method.getAnnotation(PreAuthorize.class);
                    // 判断自定义注解是否为空，为null说明不需要校验权限，否则继续校验
                    if (annotation!=null){
                        // 拿到自定义注解的value值
                        String value = annotation.value();
                        // 查询出来当前用户的premission
//                     List<String> sns = permissionMapper.selectPremission(lf.getId());
                        List<String> sns = userInfo.getSns();
                        // 判断该用户所有权限是否包含当前value
                        if (    sns.contains(value)){
                            // 如果包含 放行，否者  noPermission
                            return true;
                        }

                    }
                    // 超级重要 返回给前端json响应头的时候一定加上respone的相应类型 加载写的前面
                    resp.setContentType("application/json;charset=UTF-8");
                    PrintWriter writer = resp.getWriter();
                    writer.println("{\"success\":false,\"message\":\"noPremission\"}");
                    return false;



                }
                // 说明本地token存在并且没有过期
                // 刷新登陆信息
//                redisTemplate.opsForValue().set(token,o,30, TimeUnit.MINUTES);
                return true;
            }
        }
        // 被拦截的情况
        // 返回没有登陆的json数据给前端  让前端去进行页面跳转  携带参数在respond响应体里
        /**
         * 使用reepon
         * {"success":false,"message":"noAuth"}
         *
         */
        // 超级重要 返回给前端json响应头的时候一定加上respone的相应类型 加载写的前面
        resp.setContentType("application/json;charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        writer.println("{\"success\":false,\"message\":\"noAuth\"}");
        return false;
    }
}
